package com.zlcx.tz.live.service.impl;

import com.zlcx.tz.live.domain.TimeLearnRoomUsersDO;
import com.zlcx.tz.live.exception.UnRoomUserException;
import com.zlcx.tz.live.service.TimeLearnRoomDialogStore;
import com.zlcx.tz.live.service.TimeLearnRoomService;
import com.zlcx.tz.live.vo.DialogVO;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: anjl
 * @description:
 * @data: 2020-11-03
 **/
@Slf4j
@Service
public class RedisTimeLearnRoomDialogStoreImpl implements TimeLearnRoomDialogStore {

    @Override
    public List<DialogVO> all(Long roomId) {
        RMapCache<Long, Date> dialogStore = getRedisRoomUserStore(roomId);
        return dialogStore.readAllKeySet()
                .stream()
                .map(k ->
                        DialogVO.builder()
                                .userId(k)
                                .time(dialogStore.get(k))
                                .build())
                .collect(Collectors.toList());
    }

    public void add(Long roomId, Long userId) throws UnRoomUserException {
        Date now = new Date();
        RMapCache<Long, Date> dialogStore = getRedisRoomUserStore(roomId);
        if (dialogStore.containsKey(userId)) {
            Date date = dialogStore.get(userId);
            dialogStore.replace(userId, date, now);
            log.info("计时房间操作-更新房间心跳时间，now = {} roomId = {} userId = {}", now, roomId, userId);
        } else {
            TimeLearnRoomUsersDO roomUser = timeLearnRoomService.findByUserId(userId);
            if (Objects.isNull(roomUser)) {
                throw new UnRoomUserException("用户不在房间内 roomId = " + roomId + "userId = " + userId);
            }
            dialogStore.putIfAbsent(userId,
                    now, REDIS_TIME_LEARN_ROOM_TIME_OUT,
                    TimeUnit.DAYS, REDIS_TIME_LEARN_ROOM_MAX_IDLE_TIME,
                    TimeUnit.MINUTES);
            log.info("计时房间操作-用户第一次心跳，将用户信息放入会话中 roomId = {} userId = {}", roomId, userId);
        }
    }

    @Override
    public void remove(Long roomId, Long userId) {
        RMapCache<Long, Date> dialogStore = getRedisRoomUserStore(roomId);
        dialogStore.remove(userId);
    }

    private RMapCache<Long, Date> getRedisRoomUserStore(Long roomId) {
        return redissonClient.getMapCache(TIME_LEARN_ROOM_DIALOG + roomId);
    }

    @Autowired
    private RedissonClient redissonClient;
    @Lazy
    @Autowired
    private TimeLearnRoomService timeLearnRoomService;
    //房间会话key
    private static final String TIME_LEARN_ROOM_DIALOG = "tz-live-video:time-learn-room:dialog";
    //redis channel key过期时间，设置0为永不过期 单位：分钟
    private static final long REDIS_TIME_LEARN_ROOM_TIME_OUT = 0;
    //redis channel活跃时长，超过时长没有任何操作，自动删除，单位：分钟
    private static final long REDIS_TIME_LEARN_ROOM_MAX_IDLE_TIME = 3;
    //心跳时长
    public static final long HEART_INTERVAL = 30;//单位：秒
}
